package org.devcp.tp.common.websocket;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.devcp.tp.common.event.SysEvent;
import org.devcp.tp.common.event.SysEventRegister;
import org.devcp.tp.common.event.listner.SysEventListener;
import org.devcp.tp.common.event.util.SysEventUtil;
import org.devcp.tp.common.websocket.model.WebsocketSessionWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.alibaba.fastjson.JSONObject;

//@Service
//public class SysHandler implements WebSocketHandler {
	public class RoomHandler extends TextWebSocketHandler{
	
	private static final Logger logger = Logger.getLogger(RoomHandler.class);
	

//    @Resource
//    private BootstrapHandlerService bootstrapHandlerService;
//    @Resource
//    private Cached cached;
	@Autowired
	private EhCacheManager ehcacheCacheManager;
//	@Value("${sysEventRegistCacheName}")//从sysConfig.properties中来
//	private String sysEventRegistCacheName;

    /**
     * 双工通讯 连接后 并且在这里心跳
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    	logger.debug("websocket client have linked. session id : " + session.getId());
        TextMessage textMessage;
        try {
        	Map<String,WebsocketSessionWrapper> sessionMap = WebsocketSessionUtil.sessionMap;
        	final WebsocketSessionWrapper wsWrapper = new WebsocketSessionWrapper( session);
        	
        	//添加房间喊话监听
        	wsWrapper.addRoomSpeekListener(new SysEventListener() {
    			
    			@Override
    			public void onSysEvent(SysEvent event) {
    				try {
    					Map<String,Object> attr = event.getAttr();
    					String jsonDataStr = (String)attr.get("data");
    					JSONObject jsonData = JSONObject.parseObject(jsonDataStr);
    					jsonData.put("_type", "roomSpeeked");//设置推送类型为房间喊话
    					String roomId = jsonData.getString("roomId");//根据房间喊话创建的事件，所封装的数据模型结构对比，获取到喊话信息id
    					
						WebSocketSession s = wsWrapper.getSession();
						
						String curRoomId = (String)s.getAttributes().get(Constants.ROOM_ID);
						//如果当前session对应的房间和当前事件中喊话信息对应的房间是同一个房间，就向该房间推送消息
						if(curRoomId.equals(roomId)){
							String data = JSONObject.toJSONString(jsonData);
							TextMessage textMessage = new TextMessage(data);
							s.sendMessage(textMessage);
						}
						
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} 
    				
    			}
    		});
        	wsWrapper.addRoomSpeekMsgDeletedListener(new SysEventListener() {
        		
        		@Override
        		public void onSysEvent(SysEvent event) {
        			try {
        				Map<String,Object> attr = event.getAttr();
        				String jsonDataStr = (String)attr.get("data");
        				JSONObject jsonData = JSONObject.parseObject(jsonDataStr);
        				jsonData.put("_type", "roomSpeekMsgDeleted");//设置推送类型为房间喊话
        				String roomId = jsonData.getString("roomId");//根据房间喊话创建的事件，所封装的数据模型结构对比，获取到喊话信息id
        				
        				WebSocketSession s = wsWrapper.getSession();
        				
        				String curRoomId = (String)s.getAttributes().get(Constants.ROOM_ID);
        				//如果当前session对应的房间和当前事件中喊话信息对应的房间是同一个房间，就向该房间推送消息
        				if(curRoomId.equals(roomId)){
        					String data = JSONObject.toJSONString(jsonData);
        					TextMessage textMessage = new TextMessage(data);
        					s.sendMessage(textMessage);
        				}
        				
        			} catch (IOException e) {
        				// TODO Auto-generated catch block
        				e.printStackTrace();
        			} 
        			
        		}
        	});
        	
        	//添加房间投票监听
        	wsWrapper.addRoomVotingListener(new SysEventListener() {
        		
        		@Override
        		public void onSysEvent(SysEvent event) {
        			try {
        				Map<String,Object> attr = event.getAttr();
        				String jsonDataStr = (String)attr.get("data");
        				JSONObject jsonData = JSONObject.parseObject(jsonDataStr);
        				jsonData.put("_type", "roomVoted");//设置推送类型为房间投票
        				String roomId = jsonData.getString("id");//根据房间喊话创建的事件，所封装的数据模型结构对比，获取到喊话信息id
        				
        				WebSocketSession s = wsWrapper.getSession();
        				String curRoomId = (String)s.getAttributes().get(Constants.ROOM_ID);
        				//如果当前session对应的房间和当前事件中喊话信息对应的房间是同一个房间，就向该房间推送消息
        				if(curRoomId.equals(roomId)){
        					
        					String data = JSONObject.toJSONString(jsonData);
        					TextMessage textMessage = new TextMessage(data);
        					s.sendMessage(textMessage);
        				}
        				
        			} catch (IOException e) {
        				// TODO Auto-generated catch block
        				e.printStackTrace();
        			} 
        			
        		}
        	});
        	
        	
        	
        	
        	
        	
        	
        	sessionMap.put(session.getId(),wsWrapper);
    		
        	
        	
//            HttpHeaders headers = session.getHandshakeHeaders();
//            String userAgent = headers.get("user-agent").get(0);
//            logger.info("LOGIN : " + userAgent);
            //构造回应的消息，每次连接成功后要回应消息吖！告诉客户端已经连接成功了！消息就在这里面构造
            textMessage = new TextMessage("ok");
        } catch (Exception e) {
            e.printStackTrace();
            textMessage = new TextMessage("fail");
        }
        //这样就发送给客户端了~ 很简单！！
        session.sendMessage(textMessage);
    }


    /**
     * 处理发送过来的消息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    @SuppressWarnings(value={"unchecked","rawtypes"})
    public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception {
        try {
        	//如果连接成功！！这里面会不停的接收到心跳包！！ 怎么处理~看你的了！！！ 总之这个方法就是接受客户端发来消息的方法！！！

        	// message.getPayload()得到的是客户端发来的消息，比如“你好啊！” 之类的。得到后转成String就能处理了！
            StringBuffer sb = new StringBuffer((String) message.getPayload());
            System.out.println(sb);
            //这个是我自己写的一个处理业务逻辑。你可以实现自己的业务逻辑
//            bootstrapHandlerService.handleMessage(session, sb);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
    }
    
    @Override
	public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//		String reply = this.echoService.getMessage(message.getPayload());
		StringBuffer sb = new StringBuffer((String) message.getPayload());
		session.sendMessage(new TextMessage(sb));
	}

    /**
     * 客户端 异常断开
     *
     * @param session
     * @param throwable
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
    	logger.info(session.getId() +" - 异常断开连接");
        //所谓异常断开，例如：突然关闭HTML页面等等，总之不是用户正常关闭的！
    	//这个也是我自己实现的 异常处理的业务逻辑，你可以自己写
//        bootstrapHandlerService.handleError(session, throwable);
    	
    	
    }

    /**
     * 连接已经断 开
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
    	//只要是断开连接！不管是异常断开，还是普通正常断开，一定会进入这个方法。
        String reason = status.getReason();
        if (reason == null) {
            reason = "客户端 按指令正常退出";
        }
        removeSession(session);
        //从事件注册表中移除该session绑定的注册信息
        WebsocketSessionWrapper.removeRegisterMap(session);
        
        logger.info(session.getId() + " - 已经主动关闭连接 - 关闭码 - " + status.getCode() + " - 缘由 -" + reason);
        //其实这里面封装了个session.close()释放了一些资源， 也是我自己实现的业务逻辑，你也可以自己写！
//        bootstrapHandlerService.connectionClose(session);
    }

    /**
     * 握手成功 初始化操作在这里面进行
     *
     * @return
     */
    @Override
    public boolean supportsPartialMessages() {
    	//一旦HTTP认证成功 这个方法先被调用 如果返回true 则进行上面那么N多方法的流程。如果返回的是false就直接拦截掉了。不会调用上面那些方法了！！
         //就好像个构造器一样。这个是处理器 BootstrapHandler的构造器~
        return true;
    }
    
    

    private void removeSession(WebSocketSession session){
    	 WebsocketSessionUtil.sessionMap.remove(session.getId());
    	//移除关闭session
//    	String sysEventRegistCacheName = ResourceUtil.getConfigByName("sysEventRegistCacheName");
//		List<Session> sessionList = (List<Session>)ehcacheCacheManager.getCache(sysEventRegistCacheName).get("websocketSessionList");
//    	List<WebsocketSessionWrapper> sessionList = WebsocketSessionUtil.sessionList;
//		if(sessionList != null){
//			String sessionId = session.getId();
//			for(int i = 0  ; i < sessionList.size() ; i++){
//				if(sessionList.get(i).getSession().getId().equals(sessionId)){
//					sessionList.remove(i);
//					break;
//				}
//			}
////			ehcacheCacheManager.getCache(sysEventRegistCacheName).put("websocketSessionList", sessionList);
//		}
    }
}
